package com.pactera.asmp.server.restfullapi;

import java.io.IOException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.pactera.asmp.server.common.constants.Constants;
import com.pactera.asmp.server.common.constants.PermissionCode;
import com.pactera.asmp.server.common.constants.ResultCode;
import com.pactera.asmp.server.common.logprint.utils.StringUtils;
import com.pactera.asmp.server.entity.ResponseResult;
import com.pactera.asmp.server.entity.UseCaseInfoSearchDTO;
import com.pactera.asmp.server.pojo.UseCaseInfo;
import com.pactera.asmp.server.service.UseCaseService;
import com.pactera.asmp.server.utils.PageDataResult;

@RestController
@RequestMapping("/api/v1")
public class RestfulUseCaseApi {

    private static final Logger logger = LoggerFactory.getLogger(RestfulUseCaseApi.class);

    @Autowired
    private UseCaseService useCaseService;

    @RequiresPermissions({PermissionCode.TEST_CASE})
    @PostMapping(value = "/usecase/list", produces = "application/json;charset=UTF-8")
    public ResponseResult getUseCaseList(@RequestBody UseCaseInfoSearchDTO useCaseInfoSearchDTO) {
        logger.info("POST /api/v1/usecase/list getUseCaseList" );
        ResponseResult responseResult = new ResponseResult(ResultCode.SUCCESS);
        PageDataResult pdr ;
        JSONObject jsonObject = new JSONObject();
        if (null == useCaseInfoSearchDTO.getPage() || useCaseInfoSearchDTO.getPage().intValue() == 0) {
            useCaseInfoSearchDTO.setPage(1);
        }
        if (null == useCaseInfoSearchDTO.getLimit() || useCaseInfoSearchDTO.getLimit().intValue() == 0) {
            useCaseInfoSearchDTO.setLimit(10);
        }

        if(useCaseInfoSearchDTO.getPage().intValue() < 0 || useCaseInfoSearchDTO.getLimit().intValue() < 0) {
            jsonObject.put("totals", 0);
            jsonObject.put("list", Lists.newArrayList());
            responseResult.setData(jsonObject);
            return responseResult;
        }

        pdr = useCaseService.select(useCaseInfoSearchDTO);
        jsonObject.put("totals", pdr.getTotals());
        jsonObject.put("list", pdr.getList());
        responseResult.setData(jsonObject);
        return responseResult;
    }

    @PostMapping(value = "/usecase",  produces = "application/json;charset=UTF-8")
    public ResponseResult addUseCase(@RequestBody UseCaseInfo useCaseInfo) {
        logger.info("POST /api/v1/usecase addUseCase");
        if (null == useCaseInfo) {
            return new ResponseResult(ResultCode.PARAM_IS_BLANK);
        }
        if (StringUtils.isEmpty(useCaseInfo.getName())
                || useCaseInfo.getProjectId() == null
//                || StringUtils.isEmpty(useCaseInfo.getProjectName())
                || StringUtils.isEmpty(useCaseInfo.getExpectResult())
                || StringUtils.isEmpty(useCaseInfo.getPreCondition())
                || StringUtils.isEmpty(useCaseInfo.getTestProcedure())) {
            return new ResponseResult(ResultCode.PARAM_NOT_COMPLETE);
        }
        if(!useCaseInfo.getName().matches(Constants.REGEXP_FIRST_LAST_NOT_SPACE)) {
            return new ResponseResult(ResultCode.PARAM_TYPE_BIND_ERROR);
        }
        UseCaseInfo info = useCaseService.insert(useCaseInfo);
        return ResponseResult.defaultSuccess(info.getId());
    }

    @PutMapping(value = "/usecase",  produces = "application/json;charset=UTF-8")
    public ResponseResult updateUseCase(@RequestBody UseCaseInfo useCaseInfo) {
        logger.info("PUT /api/v1/usecase updateUseCase");
        if (null == useCaseInfo) {
            return new ResponseResult(ResultCode.PARAM_IS_BLANK);
        }
        if (null == useCaseInfo
                || useCaseInfo.getId() == null
                || StringUtils.isEmpty(useCaseInfo.getName())
                || StringUtils.isEmpty(useCaseInfo.getExpectResult())
                || StringUtils.isEmpty(useCaseInfo.getPreCondition())
                || StringUtils.isEmpty(useCaseInfo.getTestProcedure())) {
            return new ResponseResult(ResultCode.PARAM_NOT_COMPLETE);
        }
        if (StringUtils.isNotEmpty(useCaseInfo.getName())) {
            if(!useCaseInfo.getName().matches(Constants.REGEXP_FIRST_LAST_NOT_SPACE)) {
                return new ResponseResult(ResultCode.PARAM_TYPE_BIND_ERROR);
            }
        }
        handleUpdateTime(useCaseInfo);
        return useCaseService.update(useCaseInfo) ? new ResponseResult(ResultCode.SUCCESS) : new ResponseResult(ResultCode.SYSTEM_INNER_ERROR);
    }

    private void handleUpdateTime(UseCaseInfo useCaseInfo) {
        Date date = new Date();
        Instant instant = date.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDateTime updateTime = instant.atZone(zoneId).toLocalDateTime();
        useCaseInfo.setUpdateTime(updateTime);
    }

    @DeleteMapping(value = "/usecase/{id}", produces = "application/json;charset=UTF-8")
    public ResponseResult deleteUseCase(@PathVariable("id") Long id) {
        logger.info("delete /api/v1/usecase deleteUseCase ");
        if (id == null) {
            return new ResponseResult(ResultCode.PARAM_IS_BLANK);
        }
        return useCaseService.delete(id) ? new ResponseResult(ResultCode.SUCCESS) : new ResponseResult(ResultCode.SYSTEM_INNER_ERROR);
    }

    @PostMapping(value = "/usecase/{id}", produces = "application/json;charset=UTF-8")
    public ResponseResult useCaseDetail(@PathVariable("id") Long id) {
        return useCaseService.useCaseDetail(id);
    }

    @PostMapping(value = "/usecase/import")
    public ResponseResult importUseCase(@RequestParam(value = "file") MultipartFile file, HttpServletRequest request) {
        return useCaseService.importUseCases(file);
    }

    /**
     * 导出用例信息
     * 
     * @param
     * @param
     * @param
     * @throws IOException
     */
    @RequestMapping(value = "/usecase/export", method = RequestMethod.POST)
    public void exportUsercase(@RequestBody UseCaseInfoSearchDTO useCaseInfoSearchDTO, HttpServletRequest request,
            HttpServletResponse response) throws IOException {
        logger.info("Post /api/v1/usecase/export exportUsercase {}" + JSONObject.toJSONString(useCaseInfoSearchDTO));
        useCaseService.export(useCaseInfoSearchDTO, response);
    }

    /**
     * 导出用例模板
     * 
     * @param request
     * @param response
     * @throws IOException
     */
    @RequestMapping(value = "/usecase/export/model", method = RequestMethod.POST)
    public void exportUsercaseModel(HttpServletRequest request, HttpServletResponse response) throws IOException {
        logger.info("Post /usecase/export/model exportUsercaseModel");
        useCaseService.exportModel(response);
    }

}
